package com.drinkian.authentication.service.impl;

import com.drinkian.authentication.entity.vo.VUser;
import com.drinkian.entity.RequestResult;
import com.drinkian.authentication.entity.bo.SecurityUser;
import com.drinkian.authentication.entity.po.User;
import com.drinkian.authentication.service.ILoginService;
import com.drinkian.utils.JwtUtil;
import com.drinkian.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public RequestResult login(User user) {
//        1 AuthenticationManager authenticate认证
//          1.1 这里的认证需要介入spring-security的认证管理，也就是我们配置类中暴露的AuthenticationManager，调用它的authenticate方法进行认证即可
//          1.2 其实这里会使用我们自定义继承了UserDetailsService的UserDetailsServiceImpl实现类的loadUserByUsername方法进行认证
//              这个继承类的作用是可以书写我们自己的逻辑进行用户认证，也就是去数据库中查数据，默认的方式是去内存中查询
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate;
        try {
            authenticate = authenticationManager.authenticate(authenticationToken);
        } catch (RuntimeException exception) {
            return new RequestResult(HttpStatus.UNAUTHORIZED.value(), exception.getMessage());
        }
//        2.1 认证没通过，给出相关提示
        if(Objects.isNull(authenticate)) {
            return new RequestResult(HttpStatus.UNAUTHORIZED.value(), "账号或者密码错误！");
        }
//        2.2 认证通过了，使用user.id生成一个jwt
        SecurityUser securityUser = (SecurityUser) authenticate.getPrincipal();
        String token = jwtUtil.getToken(securityUser.getUser().getId());
//        3.1 把用户完整信息存入redis，user.id作为key
        redisUtil.set("user_id_"+securityUser.getUser().getId(),securityUser);
        SecurityUser principal = (SecurityUser) authenticate.getPrincipal();
        VUser vUser = new VUser(principal.getUser(),principal.getRoleList(), principal.getPermissionList(), token);
        return new RequestResult(HttpStatus.OK.value(), vUser);
    }

    @Override
    public RequestResult logout() {
        // 1.1 通过SecurityContextHolder获得Authentication对象，进而获得登录用户的信息
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();
        redisUtil.del("user_id_"+securityUser.getUser().getId());
        return new RequestResult(HttpStatus.OK.value(),"登出成功！");
    }
}
